﻿using Audit.Core;
using Dapper;
using Dapper_Core.BLL.Interface;
using Dapper_Core.Common;
using Dapper_Core.DAL.Impl;
using Dapper_Core.Model;
using Dapper_Core.Table;
using ExpressionToWhere;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;

namespace Dapper_Core.BLL.Impl
{
    public class Sys_MenuBusiness : BaseRepository<Sys_Menu>, ISys_MenuBusiness
    {
        public Sys_MenuBusiness()
        {

        }

        public Sys_MenuBusiness(TransactionContext transactionContext) : base(transactionContext)
        {

        }

        public bool IsExist(string menuCode, string menuId = "")
        {
            try
            {
                if (string.IsNullOrEmpty(menuCode)) return true;
                Expression<Func<Sys_Menu, bool>> exp = menu => menu.MenuCode == menuCode;
                List<Sys_Menu> list = base.GetList(exp, false).ToList();
                if (list != null && list.Count > 0 && list[0].MenuId != menuId) return true;
                return false;
            }
            catch (Exception ex)
            {
                NlogUtility.WriteError(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName, "检查系统资源是否存在失败", "menuCode=" + menuCode + "，menuId=" + menuId, ex, "DapperCore");
                return false;
            }
        }

        public bool Add(Sys_Menu menu)
        {
            using (AuditScope scope = AuditScope.Create("Sys_Menu:Add", () => menu))
            {
                try
                {
                    scope.Comment("添加单个系统资源项");
                    scope.SetCustomField("Module", "Sys_Menu");
                    scope.SetCustomField("Operator", SessionUtility.GetBasicUserInfo().PinyinCode);
                    scope.SetCustomField("Operation", Operation.Insert);
                    bool success = base.Add(menu);
                    if (!success)
                    {
                        scope.Discard();
                    }
                    return success;
                }
                catch (Exception ex)
                {
                    scope.Discard();
                    NlogUtility.WriteError(MethodBase.GetCurrentMethod().DeclaringType.FullName, "系统资源添加失败", "menu=" + JsonConvert.SerializeObject(menu), ex, "DapperCore");
                    return false;
                }
            }
        }

        public bool UpdateNotNull(Sys_Menu menu)
        {
            Sys_Menu old = base.Get(menu.MenuId);
            using (AuditScope scope = AuditScope.Create("Sys_Menu:Edit", () => old))
            {
                try
                {
                    scope.Comment("编辑单个系统资源项");
                    scope.SetCustomField("Module", "Sys_Menu");
                    scope.SetCustomField("Operator", SessionUtility.GetBasicUserInfo().PinyinCode);
                    scope.SetCustomField("Operation", Operation.Update); 
                    old = menu;
                    bool success = base.UpdateNotNull(menu);
                    if (!success)
                    {
                        scope.Discard();
                    }
                    return success;
                }
                catch (Exception ex)
                {
                    scope.Discard();
                    NlogUtility.WriteError(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName, "系统资源修改失败", "menu=" + JsonConvert.SerializeObject(menu), ex, "DapperCore");
                    return false;
                }
            }
        }

        public bool Delete(string ids, string deleter)
        {
            using (AuditScope scope = AuditScope.Create("Sys_Menu:Delete", () => ids))
            {
                try
                {
                    if (string.IsNullOrEmpty(ids)) return true;
                    List<string> idList = ids.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList();
                    if (idList.Count < 1) return true;
                    scope.Comment("软删除系统资源项");
                    scope.SetCustomField("Module", "Sys_Menu");
                    scope.SetCustomField("Operator", deleter);
                    scope.SetCustomField("Operation", Operation.Delete);
                    //定义时间变量，保证同一次删除数据的删除时间相等
                    DateTime dateTime = DateTime.Now;
                    Expression<Func<Sys_Menu, bool>> exp = menu => menu.MenuId.In(idList);
                    bool success = base.SoftDelete(exp, deleter, dateTime);
                    if (!success)
                    {
                        scope.Discard();
                    }
                    return success;
                }
                catch (Exception ex)
                {
                    scope.Discard();
                    NlogUtility.WriteError(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName, "系统资源软删除失败", "ids=" + ids, ex, "DapperCore");
                    return false;
                }
            }
        }

        public List<Sys_MenuExtend> GetExtendMenuList(string search)
        {
            try
            {
                Dictionary<string, string> dict = new Dictionary<string, string>();
                dict.Add("search", SqlUtility.GetLikeCondition(search));
                List<Sys_MenuExtend> virtualMenus = base.QueryMap<Sys_MenuExtend>("GetExtendMenuList", dict).ToList();
                NlogUtility.WriteInfo(MethodBase.GetCurrentMethod().DeclaringType.FullName, "查询系统资源信息", "search=" + search, "DapperCore");
                return SetVirtualParentCode(virtualMenus);
            }
            catch (Exception ex)
            {
                NlogUtility.WriteError(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName, "根据查询条件获取增强版系统资源信息列表失败", "search=" + search, ex, "DapperCore");
                return new List<Sys_MenuExtend>();
            }
        }

        public List<Sys_ZTreeMenu> GetMenuPermissionList(string roleCode)
        {
            try
            {
                Expression<Func<Sys_Role_Menu, bool>> roleMenuExp = roleMenu => roleMenu.RoleCode == roleCode;
                List<Sys_Menu> menus = this.GetList("").ToList();
                List<Sys_Role_Menu> roleMenus = new BaseRepository<Sys_Role_Menu>().GetList(roleMenuExp).ToList();
                return GetZTreeMenus(menus, roleMenus, "0");
            }
            catch (Exception ex)
            {
                NlogUtility.WriteError(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName, "获取“系统资源 - 角色有权访问的系统资源”之间的对应关系失败", "roleCode=" + roleCode, ex, "DapperCore");
                return new List<Sys_ZTreeMenu>();
            }
        }

        public List<string> GetAllMenuPageUrls(string userCode, string roleCode)
        {
            try
            {
                List<string> pageUrls = GetAllMenuPageUrlsByUser(userCode);
                if (pageUrls == null || pageUrls.Count == 0)
                {
                    pageUrls = GetAllMenuPageUrlsByRole(roleCode);
                }
                return pageUrls;
            }
            catch (Exception ex)
            {
                NlogUtility.WriteError(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName, "获取用户所拥有资源的PageUrl失败", "userCode=" + userCode, ex, "DapperCore");
                return new List<string>();
            }
        }

        public List<string> GetAllMenuPageUrlsByUser(string userCode)
        {
            try
            {
                Dictionary<string, string> dict = new Dictionary<string, string>();
                dict.Add("userCode", userCode);
                return base.QueryMap<string>("GetAllMenuPageUrlsByUser", dict).ToList();
            }
            catch (Exception ex)
            {
                NlogUtility.WriteError(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName, "获取用户所拥有资源的PageUrl失败", "userCode=" + userCode, ex, "DapperCore");
                return new List<string>();
            }
        }

        public List<string> GetAllMenuPageUrlsByRole(string roleCode)
        {
            try
            {
                Dictionary<string, string> dict = new Dictionary<string, string>();
                dict.Add("roleCode", roleCode);
                return base.QueryMap<string>("GetAllMenuPageUrlsByRole", dict).ToList();
            }
            catch (Exception ex)
            {
                NlogUtility.WriteError(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName, "获取角色所拥有资源的PageUrl失败", "roleCode=" + roleCode, ex, "DapperCore");
                return new List<string>();
            }
        }

        public List<string> GetAllMenusCode(string userCode, string roleCode)
        {
            try
            {
                List<string> pageUrls = GetAllMenusCodeByUser(userCode);
                if (pageUrls == null || pageUrls.Count == 0)
                {
                    pageUrls = GetAllMenusCodeByRole(roleCode);
                }
                return pageUrls;
            }
            catch (Exception ex)
            {
                NlogUtility.WriteError(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName, "获取用户所拥有资源的Code失败", "userCode=" + userCode, ex, "DapperCore");
                return new List<string>();
            }
        }

        public List<string> GetAllMenusCodeByUser(string userCode)
        {
            try
            {
                Dictionary<string, string> dict = new Dictionary<string, string>();
                dict.Add("userCode", userCode);
                return base.QueryMap<string>("GetAllMenusCodeByUser", dict).ToList();
            }
            catch (Exception ex)
            {
                NlogUtility.WriteError(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName, "获取用户所拥有资源的Code失败", "userCode=" + userCode, ex, "DapperCore");
                return new List<string>();
            }
        }

        public List<string> GetAllMenusCodeByRole(string roleCode)
        {
            try
            {
                Dictionary<string, string> dict = new Dictionary<string, string>();
                dict.Add("roleCode", roleCode);
                return base.QueryMap<string>("GetAllMenusCodeByRole", dict).ToList();
            }
            catch (Exception ex)
            {
                NlogUtility.WriteError(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName, "获取角色所拥有资源的Code失败", "roleCode=" + roleCode, ex, "DapperCore");
                return new List<string>();
            }
        }

        private List<Sys_MenuExtend> SetVirtualParentCode(List<Sys_MenuExtend> menus)
        {
            foreach (Sys_MenuExtend menu in menus)
            {
                menu.VirtualParentCode = GetVirtualParentCode(menus, menu);
            }
            return menus;
        }

        private string GetVirtualParentCode(List<Sys_MenuExtend> menus, Sys_MenuExtend menu)
        {
            if (menu.ParentCode == "0") return menu.ParentCode;
            if (menus.Where(a => a.MenuCode == menu.ParentCode).Count() > 0) return menu.ParentCode;
            return "0";
        }

        private List<Sys_ZTreeMenu> GetZTreeMenus(List<Sys_Menu> menus, List<Sys_Role_Menu> roleMenus, string parentCode)
        {
            List<Sys_ZTreeMenu> zTreeMenus = new List<Sys_ZTreeMenu>();
            Sys_ZTreeMenu zTreeMenu = null;
            List<Sys_Menu> children = menus.Where(a => a.ParentCode == parentCode).OrderBy(a => a.MenuId).ToList();
            foreach (Sys_Menu menu in children)
            {
                zTreeMenu = new Sys_ZTreeMenu();
                zTreeMenu.id = menu.MenuCode;
                zTreeMenu.pId = menu.ParentCode;
                zTreeMenu.name = menu.MenuName;
                zTreeMenu.open = false;
                zTreeMenu.@checked = roleMenus.Where(a => a.MenuId == menu.MenuId).Count() > 0;
                zTreeMenu.menuId = menu.MenuId;
                zTreeMenu.children = GetZTreeMenus(menus, roleMenus, menu.MenuCode);
                if (zTreeMenu.children.Count < 1)
                {
                    zTreeMenu.iconSkin = "doc";
                    zTreeMenu.isParent = false;
                }
                else
                {
                    zTreeMenu.isParent = true;
                }
                zTreeMenus.Add(zTreeMenu);
            }
            return zTreeMenus.OrderBy(a => a.id).ToList();
        }
    }
}